home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 842 < prev    next >
Encoding:
Text File  |  1996-08-06  |  4.6 KB  |  122 lines

  1. Path: chronicle.mti.sgi.com!austern
  2. From: Philippe Verdy <100105.3120@compuserve.com>
  3. Newsgroups: comp.std.c++
  4. Subject: constness of private members and methods
  5. Date: 25 Mar 1996 10:04:56 PST
  6. Organization: CompuServe Incorporated
  7. Approved: austern@isolde.mti.sgi.com
  8. Message-ID: <4j49e0$8fo@dub-news-svc-4.compuserve.com>
  9. NNTP-Posting-Host: isolde.mti.sgi.com
  10. X-Original-Date: 24 Mar 1996 19:56:48 GMT
  11. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  12.     iQBVAwUBMVbgV0y4NqrwXLNJAQFmJQH/WLQML6cwTrsQ7ff4Ill7GUEKrP/5hjog
  13.     QP9gzv3KSMjbkVEL1oCxfrb+uj9E8o9kobAJQkYRF7KKOHppoVe7rA==
  14.     =Mt3Q
  15. Originator: austern@isolde.mti.sgi.com
  16.  
  17. Many recursive data structures require algorithms to handle
  18. them which have to mark and unmark all scanned objects in
  19. order to avoid infinite recursion when walking on that
  20. structure, or when building items iterator.
  21. Such algorithms will use the mark() and unmark() private
  22. methods in each visited node, so that we can detect paths
  23. which have already been visited. his is critical for example
  24. when managing with auto-references, graphs, dictionnaries
  25. of polymorphic objects (containing dictionnaries like in
  26. a PostScript interpret).
  27. However, how can we apply standard read-only methods on such
  28. objects: these methods are specified as const in one of the
  29. base classes, and virtual override requires not to change the
  30. constness of the derived object.
  31. So we cannot mark such structures, because even a private
  32. member cannot be modified in a const instance.
  33. We can effectively change temporarily the constness of the
  34. object to realize this mark, but in that case we would write
  35. the following :
  36.   class T {
  37.   public:
  38.     T()                   { ...; _mark = 0; }
  39.     virtual ~T();
  40.  
  41.     virtual void show() const;
  42.   protected:
  43.     void mark()           { _mark = 1; }
  44.     void unmark()         { _mark = 0; }
  45.     bool ismarked() const { return _mark; }
  46.   private:
  47.     char _mark;
  48.   }
  49. The problem is that now mark() and unmark() methods are not
  50. const so they cannot be used in read-only methods like show().
  51. So we have to use a const_cast<T&> or const_cast<T*> to
  52. suppress this constness.
  53.  
  54. This is not obvious, and has the big disadvantage of globally
  55. suppressing the constness of the object. So this is quite
  56. dangerous, because some-times, we do not know really if a
  57. method has an impact on the semantic value of the instance
  58. on which we apply this cast. So this is a security hole which
  59. should be avoided.
  60.  
  61. We can avoid const_casting to call mark() and unmark() by
  62. declaring them as const, like this:
  63.   protected:
  64.     void mark() const   { (const_cast<T*>this)->_mark = 1; }
  65.     void unmark() const { (const_cast<T*>this)->_mark = 0; }
  66. but this is really hard to write, and is it semantically
  67. correct ? It would from the public point of view, but what
  68. on the private point of view ?
  69.  
  70. We can also use explicitly (const_cast<T*>this)->mark(); and
  71. (const_cast<T*>this)->unmark(); calls in the show()
  72. implementation, but this is quite hard to write, so that many
  73. users refrain using const specifiers on their classes.
  74.  
  75. Is there any way (or proposal) to explicitly specify members
  76. of a class definition which are relaxed on constness certi-
  77. fication ?
  78.  
  79. Would not it be great if we could simply define such members
  80. as "unconst" like in the following example :
  81.  
  82.   class T {
  83.   public:
  84.     T()                   { ...; _mark = 0; }
  85.     virtual ~T();
  86.  
  87.     virtual void show() const;
  88.   protected:
  89.     void mark() const     { _mark = 1; } // RELAXED HERE
  90.     void unmark() const   { _mark = 0; } // RELAXED HERE
  91.     bool ismarked() const { return _mark; }
  92.   private:
  93.     unconst char _mark; // HERE IS WHERE THIS APPLIES
  94.   }
  95.  
  96. In that example, even thow the mark() and unmark() methods
  97. are const-specified, we are allowed to modify the _mark
  98. member, because it has been explicitly relaxed.
  99.  
  100. We could restrict the unconst modifier usage to private
  101. or protected members declaration only, so that the public
  102. interface of a class would keep the constness integrity.
  103.  
  104. This way, the dangerous const_cast<> operator could be avoided
  105. most of the time and isolated in specific class
  106. implementations (for compatibility with not const-compliant
  107. C libraries)...
  108.  
  109. What do you think ?
  110.  
  111. And is constness definition a semantic only definition,
  112. or does it involve a more strict sense in which the compiler
  113. optimizer would have an influence (such as in common
  114. subexpressions reduction) ?
  115. ---
  116. [ comp.std.c++ is moderated.  To submit articles: Try just posting with your 
  117.                 newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  118.   comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  119.   Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  120.   Comments? mailto:std-c++-request@ncar.ucar.edu 
  121. ]
  122.